#pragma once

/* 公用 */
#include <compl.h>
#include <dinfra/list.h>
#include <dbg.h>
typedef struct memrec_sized{
	void *ptr;
	size_t size;
} mecrec_sized_t;

typedef struct mecrec_nosized{
	void *ptr;
} mecrec_nosized_t;
#define MEMREC_NOSIZE
/* 方便配置 */
#ifndef MEMREC_NOSIZE
	#define MEMREC_TYPE mecrec_sized_t
#else
	#define MEMREC_TYPE mecrec_nosized_t
#endif

typedef MEMREC_TYPE memrec_t;

typedef struct {
	slist_t node;
	size_t max_nr;
	size_t used_nr;
	word_t pad;
	memrec_t rec[];
} recbatch_t;

SAI size_t recbatch_size(size_t memrec_nr){
	return sizeof(recbatch_t) + sizeof(memrec_t) * memrec_nr;
}

SAI recbatch_t *recbatch_init(void *ptr, size_t size, size_t memrec_nr){
	// ASSERT(ptr && size <= recbatch_size(memrec_nr));
	recbatch_t *ret = (recbatch_t *)ptr;
	ret->max_nr = memrec_nr;
	ret->used_nr = 0;
	__memset(&ret->rec[0], 0, sizeof(memrec_t) * memrec_nr);
	return ret;
}
/* 基本操作 */
SAI void recbatch_push_rec(recbatch_t *b, void *ptr, size_t size){
	size_t cur_idx = b->used_nr++;
	ASSERT(b->used_nr <= b->max_nr);
	b->rec[cur_idx].ptr = ptr;
	/* b->rec[cur_idx].size = size; */
}
SAI memrec_t *recbatch_pop_rec(recbatch_t *b){
	if (b->used_nr == 0) return NULL_PTR;
	size_t cur_idx = --b->used_nr;
	return &b->rec[cur_idx];
}
/* 打乱 */
SAI void recbatch_shuffle(recbatch_t *b, word_t cur_iter_idx){
	ASSERT(b->used_nr >= 1);
	shuffle(b->rec, b->used_nr, rdcnt_relax(), cur_iter_idx);
}

/* */
/* 引入锁 */
#include <ddblk/locks.h>
static slist_t *head = NULL_PTR; 
static slist_t *tail = (slist_t *)&head;
static spinlock_t l;
// static pthread_mutex_t mt = {0};
SNI recbatch_t *recbatch_exchange_locked(recbatch_t *b){


	// recbatch_t *ret;
	// slist_t *cur_head;
	// b->node.next = NULL_PTR;
	// spin_lock(&l, NULL_PTR);
	// // pthread_mutex_lock(&mt);
	// /* 临界区 */
	// ret = list_entry(recbatch_t, head, node);
	// // ASSERT(ret != NULL);
	// tail->next = &b->node;
	// head = ret->node.next;
	// tail = &b->node;
	// /* 临界区 */
	// // pthread_mutex_unlock(&mt);
	// spin_unlock(&l, NULL_PTR);


	/* 直接替换呢? */
	return (recbatch_t *)swp_rel(&head, &b->node);


	// return ret;
}